﻿#pragma once
#include <iostream>
// #include <fstream>
#include <string>

// C 库
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <memory.h>
#include <cstdint>
#if defined(_WIN32) || defined(_WIN64)
    #include <windows.h>
#else
    #include <unistd.h>
#endif


#ifndef _CFileBase_H_
    #define _CFileBase_H_

class CFileBase
{
public:
    // default constructor
    CFileBase();
    CFileBase(const char* sz_file_name);
    CFileBase(const std::string& str_file_name);
    CFileBase(const CFileBase& file);
    CFileBase(CFileBase&& file) noexcept;
    CFileBase& operator=(const CFileBase& file);
    CFileBase& operator=(CFileBase&& file) noexcept;
    virtual ~CFileBase();

    // 打开文件，返回是否成功，没有文件会自动创建
    bool open_file(const char* sz_file_name, const char* mode = "r+");

    // 关闭文件，返回是否成功
    bool close_file();

    // 获取当前工作目录，返回绝对路径字符串
    const char* get_cwd();

    // 获取文件名，不包含路径
    const char* get_file_name() const;

    // 移动文件指针 pos_ 到 pos
    inline void seek_to(int64_t pos);
    
    // 移动文件指针到文件开始
    void seek_start();
    
    // 移动文件指针到文件末尾
    void seek_end();
    
    // 获取文件指针位置
    int64_t tell_pos();

    // 读取到 file_content_
    void read_line();
    
    // 读取到 file_content_
    void read_all();
    
    // 读取到 file_content_
    void read_size(size_t size);

    // 从当前 pos_ 位置开始读取一行，并读取到 str_line，返回读取的字节数
    int64_t read_line(std::string& str_line);
    
    // 从当前 pos_ 位置开始读取文件，并读取到 str_all
    int64_t read_all(std::string& str_all);
    
    // 从当前位置开始读取 size 字节，并读取到 str_content
    size_t read_size(size_t size, std::string& str_content);

    // 向文件末尾写入
    size_t write_end(const char* str_end);

    // 向文件指针位置写入，根据 is_insert 判断插入/覆盖，默认覆盖
    int64_t write_pos(const char* str_content, int64_t pos, bool is_insert = false);

    // 判断文件是否是打开的
    bool is_open() const;

    // 判断文件是否是空文件
    bool is_empty() const;

    // 删除文件
    static char remove_file(const char* sz_file_name);

    // 获取调试信息
    static const char* get_debug_mag();


protected:
    FILE* file_;
    const char* mode_;

    // Change these to char* because the class allocates/frees these buffers with malloc/free.
    // Keeping them as const char* previously required casts when freeing and was semantically misleading.
    char* cwd_;
    char* file_content_;
    char* file_name_;
    
    // 文件指针位置，由 tell_pos() 获取，由 seek_to() 设置
    uint64_t pos_;
    bool is_open_;


};

extern void test_CFileBase();

#endif // _CFileBase_H_